home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / FSTSCRL1.ZIP / SOURCE.TXT < prev   
Text File  |  1995-01-10  |  15KB  |  513 lines

  1.  
  2.  
  3. This is the sourcecode for a simple 8-way scrolling demo. It includes
  4. everything except the low-level pixel copying functions, which were
  5. written in assembly and gathered in the modexc.lib file. I expect that
  6. these are pretty standard functions, although your library no doubt
  7. uses different names and perhaps slightly different arguments.
  8.  
  9. It also depends on having a .wld file in a format of my own devising,
  10. but you would have your own format for tiles and world maps, and
  11. functions for reading them in. That has nothing to do with the
  12. scrolling method anyway.
  13.  
  14. This code is released to the public domain by the author. Learn from
  15. it, use it, rewrite it... whatever you will.
  16.  
  17.      -]Frank[-
  18.  
  19. /*  -------------------  file SCROLL.H  -----------------------------------  */
  20.  
  21. #define PG_WID    88
  22. #define WLD_WID   32
  23. #define WLD_HGT   17
  24.  
  25. #define LOW_LIMIT   14848
  26.  
  27. #define BALL_WID  16
  28. #define BALL_HGT  10
  29.  
  30. typedef struct b { int x, y, oldx, oldy, xdir, ydir; } BALL;
  31.  
  32. enum { SCROLL_N, SCROLL_NE, SCROLL_E, SCROLL_SE,
  33.        SCROLL_S, SCROLL_SW, SCROLL_W, SCROLL_NW };
  34.  
  35. extern char ballmap[];
  36. extern BALL *ball;
  37. extern char pal[3*256];
  38. extern char *tiles;
  39. extern char (*world)[WLD_WID];
  40. extern int  world_rows, world_cols;
  41. extern int win_moved_x, win_moved_y;
  42.  
  43. extern int  deferred_copy;
  44.  
  45. #define  COPY_TOP  0x11
  46. #define  COPY_BOT  0x21
  47. #define  COPY_LFT  0x31
  48. #define  COPY_RGT  0x41
  49. #define  NOT_YET   0x01
  50.  
  51. extern unsigned visible_off, active_off, back_off;
  52.  
  53. extern int window_x, window_y;
  54. extern int  world_x,  world_y;
  55.  
  56. /* functions */
  57.  
  58. int read_world( char *fname, char **tiles, char **world,
  59.          int *w_rows, int *w_cols, char *pal );
  60.  
  61. void scroll_north( void ), scroll_south( void );
  62. void scroll_east( void ), scroll_west( void );
  63.  
  64. void put_tile_row( unsigned pg_off, int row, char *tiles);
  65. void put_tile_col( unsigned pg_off, int col, char *tiles);
  66.  
  67.  
  68.  
  69. /*  --------------------  file SCROLL.C   -------------------------------  */
  70.  
  71. #include <headers.h>
  72. #include <modexc.h>
  73. #include "scroll.h"
  74.  
  75. char ballmap[] = {
  76. 0,  0,  0,  0,  0,  0, 24, 24,  24, 24,  0,  0,  0,  0,  0,  0,
  77. 0,  0,  0,  0, 24, 24, 24, 24,  24, 24, 24, 24,  0,  0,  0,  0,
  78. 0,  0,  0,  0, 24, 24, 29, 29,  24, 24, 24, 24,  0,  0,  0,  0,
  79. 0,  0,  0, 24, 24, 29, 29, 24,  24, 24, 24, 24, 24,  0,  0,  0,
  80. 0,  0,  0, 24, 24, 29, 24, 24,  24, 24, 24, 24, 24,  0,  0,  0,
  81. 0,  0,  0, 24, 24, 24, 24, 24,  24, 24, 24, 24, 24,  0,  0,  0,
  82. 0,  0,  0, 24, 24, 24, 24, 24,  24, 24, 23, 24, 24,  0,  0,  0,
  83. 0,  0,  0,  0, 24, 24, 24, 24,  24, 23, 23, 24,  0,  0,  0,  0,
  84. 0,  0,  0,  0, 24, 24, 24, 24,  23, 23, 24, 24,  0,  0,  0,  0,
  85. 0,  0,  0,  0,  0,  0, 24, 24,  24, 24,  0,  0,  0,  0,  0,  0 };
  86.  
  87.  
  88. char pal[3*256];
  89. char *tiles;
  90. BALL *ball;
  91. int  num_balls;
  92.  
  93. char (*world)[WLD_WID];
  94. int  world_rows, world_cols;
  95. int win_moved_x, win_moved_y;
  96. int  deferred_copy = FALSE;
  97.  
  98. unsigned visible_off = 360,
  99.          active_off  = 22208,
  100.          back_off    = 44052;
  101.  
  102. int window_x = 16, window_y = 16;
  103. int  world_x = 0,   world_y = 0;
  104.  
  105.  
  106.   /*+----------------------------------------------------------------------+
  107.     |                                main()                                |
  108.     +----------------------------------------------------------------------+*/
  109.  
  110. void main( int argc, char *argv[] )
  111.   {
  112.    int i, dir=SCROLL_NE;
  113.    unsigned utemp, frames=0;
  114.    int old_win_x=0, old_win_y=0;
  115.  
  116.    if( argc != 2 )  num_balls = 8;
  117.    else num_balls = atoi( argv[1] );
  118.  
  119.    if( num_balls > 0 )
  120.        if( (ball=calloc(sizeof(BALL),num_balls)) == NULL )
  121.           { puts("Not enough memory");  exit(1); }
  122.  
  123.    srand( *((int far *)0x0040006cL) );
  124.  
  125.    for( i=0; i<num_balls; i++ )
  126.      {
  127.       ball[i].x = rand()%220 + 50;
  128.       ball[i].y = rand()%150 + 25;
  129.       ball[i].xdir = (rand() & 1) == 1 ? 2 : -2;
  130.       ball[i].ydir = (rand() & 1) == 1 ? 2 : -2;
  131.      }
  132.  
  133.    if( !read_world("city1.wld", &tiles,
  134.                     &world, &world_rows, &world_cols, pal) )
  135.      { puts("Can't read city1.wld");  exit(1); }
  136.  
  137.    set_mode_x();
  138.    set_page_width( 88 );
  139.    set_pallette( pal );
  140.    window_at( visible_off, window_x, window_y );
  141.  
  142.    for( i=0; i<14; i++ )
  143.       put_tile_row( back_off, i, tiles );
  144.  
  145.    rect_vram_to_vram( back_off, active_off,  0, 0, 352, 224 );
  146.    rect_vram_to_vram( back_off, visible_off, 0, 0, 352, 224 );
  147.  
  148.         /******** main loop *********/
  149.  
  150.    while( gamekey() != ESC )
  151.      {
  152.       utemp = visible_off;
  153.       visible_off = active_off;
  154.       active_off = utemp;
  155.       frames++;
  156.  
  157.       wait_retrace();
  158.       window_at( visible_off, window_x, window_y );
  159.  
  160.       if( deferred_copy )
  161.         {
  162.          switch( deferred_copy )
  163.            {
  164.             case COPY_TOP :
  165.               rect_vram_to_vram( back_off, active_off,  0, 0, 352, 16 );
  166.               break;
  167.             case COPY_BOT :
  168.               rect_vram_to_vram( back_off, active_off,  0, 224, 352, 16 );
  169.               break;
  170.             case COPY_LFT :
  171.               rect_vram_to_vram( back_off, active_off,  0, 0, 16, 240 );
  172.               break;
  173.             case COPY_RGT :
  174.               rect_vram_to_vram( back_off, active_off,  336, 0, 16, 240 );
  175.               break;
  176.             case NOT_YET  :
  177.               deferred_copy = FALSE;
  178.               break;
  179.            }
  180.          deferred_copy &= 0x01;
  181.         }
  182.  
  183.       /* erase sprites from old positions */
  184.       for( i=0; i<num_balls; i++ )
  185.          rect_vram_to_vram( back_off, active_off,
  186.                             ball[i].oldx + old_win_x - win_moved_x,
  187.                             ball[i].oldy + old_win_y - win_moved_y,
  188.                             BALL_WID, BALL_HGT );
  189.  
  190.       /* do scrolling */
  191.       win_moved_x = win_moved_y = 0;
  192.  
  193.       switch( dir )
  194.         {
  195.          case SCROLL_N   : scroll_north();
  196.                            if( frames == 440 )
  197.                              { frames = 0;  dir = SCROLL_SE; }
  198.                            break;
  199.  
  200.          case SCROLL_NE  : scroll_east();
  201.                            scroll_north();
  202.                            if( frames == 523 )
  203.                              { frames = 0;  dir = SCROLL_NW; }
  204.                            break;
  205.  
  206.          case SCROLL_E   : scroll_east();
  207.                            if( frames == 650 )
  208.                              { frames = 0;  dir = SCROLL_SW; }
  209.                            break;
  210.  
  211.          case SCROLL_SE  : scroll_east();
  212.                            scroll_south();
  213.                            if( frames == 451 )
  214.                              { frames = 0;  dir = SCROLL_E; }
  215.                            break;
  216.  
  217.          case SCROLL_S   : scroll_south();
  218.                            if( frames == 542 )
  219.                              { frames = 0;  dir = SCROLL_W; }
  220.                            break;
  221.  
  222.          case SCROLL_SW  : scroll_west();
  223.                            scroll_south();
  224.                            if( frames == 369 )
  225.                              { frames = 0;  dir = SCROLL_S; }
  226.                            break;
  227.  
  228.          case SCROLL_W   : scroll_west();
  229.                            if( frames == 255 )
  230.                              { frames = 0;  dir = SCROLL_NE; }
  231.                            break;
  232.  
  233.          case SCROLL_NW  : scroll_west();
  234.                            scroll_north();
  235.                            if( frames == 560 )
  236.                              { frames = 0;  dir = SCROLL_N; }
  237.                            break;
  238.         }
  239.  
  240.       /* check page positions */
  241.       if( active_off > 44416 )
  242.         {
  243.          utemp = active_off;
  244.          active_off = back_off;
  245.          back_off = utemp;
  246.         }
  247.  
  248.       /* save frame of reference */
  249.       old_win_x = window_x;
  250.       old_win_y = window_y;
  251.  
  252.       for( i=0; i<num_balls; i++ )
  253.         {
  254.          BALL *this = &ball[i];
  255.  
  256.          /* save ball positions */
  257.          this->oldx = this->x;
  258.          this->oldy = this->y;
  259.  
  260.          /* update ball positions */
  261.          this->x += this->xdir;
  262.          this->y += this->ydir;
  263.  
  264.          /* check collisions */
  265.          if( this->x < 2 || this->x > 301 )
  266.             this->xdir = -(this->xdir);
  267.          if( this->y < 2 || this->y > 188 )
  268.             this->ydir = -(this->ydir);
  269.  
  270.          /* draw balls in new positions */
  271.          spr_to_vram( ballmap, active_off,
  272.                       this->x + window_x,
  273.                       this->y + window_y,
  274.                       BALL_WID, BALL_HGT );
  275.         }
  276.      }        /**** end main loop ****/
  277.  
  278.    free( tiles );
  279.    free( world );
  280.    setvmode( 3 );
  281.   }
  282.  
  283. /*  ----------------------  file DOSCROLL.C  -----------------------------  */
  284.  
  285. #include <headers.h>
  286. #include <modexc.h>
  287. #include "scroll.h"
  288.  
  289.   /*+----------------------------------------------------------------------+
  290.     |     scroll_north()  scroll_south()  scroll_east()  scroll_west()     |
  291.     +----------------------------------------------------------------------+*/
  292.  
  293. void scroll_east( void )
  294.   {
  295.    if( ++window_x == 33 )
  296.      {
  297.       /* move all pages right one tile */
  298.       visible_off += 4;
  299.       active_off += 4;
  300.       back_off += 4;
  301.  
  302.       /* move right in world */
  303.       if( ++world_x == WLD_WID )  world_x = 0;
  304.  
  305.       /* grab new row of tiles */
  306.       put_tile_col( active_off, 21, tiles );
  307.  
  308.       /* copy to other pages */
  309.      rect_vram_to_vram( active_off, back_off,  336, 0, 16, 240 );
  310.      deferred_copy = COPY_RGT;
  311.  
  312.      /* reposition window */
  313.      window_x = 17;
  314.     }
  315.    win_moved_x =  1;
  316.   }
  317.  
  318.                  /*-------------------------------*/
  319.  
  320. void scroll_west( void )
  321.   {
  322.    if( --window_x < 0 )
  323.      {
  324.       /* move all pages left one tile */
  325.       visible_off -= 4;
  326.       active_off -= 4;
  327.       back_off -= 4;
  328.  
  329.       /* move left in world */
  330.       if( --world_x < 0 )  world_x += WLD_WID;
  331.  
  332.       /* grab new row of tiles */
  333.       put_tile_col( active_off, 0, tiles );
  334.  
  335.       /* copy to other pages */
  336.      rect_vram_to_vram( active_off, back_off,  0, 0, 16, 240 );
  337.      deferred_copy = COPY_LFT;
  338.  
  339.      /* reposition window */
  340.      window_x = 15;
  341.     }
  342.    win_moved_x = -1;
  343.   }
  344.  
  345.                  /*-------------------------------*/
  346.  
  347. void scroll_north( void )
  348.   {
  349.    if( --window_y < 0 )
  350.      {
  351.       /* check if we have deferred write pending */
  352.       if( deferred_copy )
  353.         {
  354.          ++window_y;               /* cancel move */
  355.          return;                   /* wait until next time */
  356.         }
  357.  
  358.       /* move all pages up one tile */
  359.       visible_off -= 16*PG_WID;
  360.       active_off -= 16*PG_WID;
  361.       back_off -= 16*PG_WID;
  362.  
  363.       /* move up in world */
  364.       if( --world_y < 0 )  world_y += WLD_HGT;
  365.  
  366.       /* grab new row of tiles */
  367.       put_tile_row( active_off, 0, tiles );
  368.  
  369.       /* copy to other pages */
  370.      rect_vram_to_vram( active_off, back_off,  0, 0, 352, 16 );
  371.      deferred_copy = COPY_TOP;
  372.  
  373.      /* reposition window */
  374.      window_y = 15;
  375.     }
  376.    win_moved_y = -1;
  377.   }
  378.  
  379.                  /*-------------------------------*/
  380.  
  381. void scroll_south( void )
  382.   {
  383.    if( ++window_y == 20 )
  384.      {
  385.       /* check if we have deferred write pending */
  386.       if( deferred_copy )
  387.         {
  388.          --window_y;               /* cancel move */
  389.          return;                   /* wait until next time */
  390.         }
  391.  
  392.       /* grab new row of tiles */
  393.       put_tile_row( active_off, 14, tiles );
  394.  
  395.       /* copy to other pages */
  396.      rect_vram_to_vram( active_off, back_off,  0, 224, 352, 16 );
  397.      deferred_copy = COPY_BOT;
  398.     }
  399.  
  400.    else if( window_y == 33 )
  401.      {
  402.       /* move all pages down one tile */
  403.       visible_off += 16*PG_WID;
  404.       active_off += 16*PG_WID;
  405.       back_off += 16*PG_WID;
  406.  
  407.       /* move down in world */
  408.       if( ++world_y == WLD_HGT )  world_y = 0;
  409.  
  410.      /* reposition window */
  411.      window_y = 17;
  412.     }
  413.    win_moved_y =  1;
  414.   }
  415.  
  416. /*  ----------------------  file DOTILES.C  -------------------------------  */
  417.  
  418. #include <headers.h>
  419. #include <modexc.h>
  420. #include "scroll.h"
  421.  
  422.   /*+----------------------------------------------------------------------+
  423.     |             read_world()  put_tile_row()  put_tile_col()             |
  424.     +----------------------------------------------------------------------+*/
  425.  
  426. int read_world( char *fname, char **tiles, char **world,
  427.                 int *w_rows, int *w_cols, char *pal )
  428.   {
  429.    signed char code, pix;
  430.    int numtiles, r, c;
  431.    char *p;
  432.    FILE *fp;
  433.  
  434.    if( (fp=fopen(fname,"rb")) == NULL )
  435.       return FALSE;
  436.  
  437.    numtiles = fgetc( fp );
  438.  
  439.    if( (*tiles=malloc(numtiles*256)) == NULL )
  440.      { fclose(fp);  return FALSE; }
  441.  
  442.      /* unpack tiles */
  443.    p = *tiles;
  444.    while( (code=fgetc(fp)) != 0 )
  445.       {
  446.        if( code > 0 )
  447.          {
  448.           pix = fgetc(fp);
  449.           while( code-- )  *p++ = pix;
  450.          }
  451.        else
  452.           while( code++ )  *p++ = fgetc(fp);
  453.       }
  454.  
  455.      /* now do world */
  456.    fread( w_rows, 2, 1, fp );     /* stored as ints */
  457.    fread( w_cols, 2, 1, fp );
  458.  
  459.    if( *w_rows!=WLD_HGT || *w_cols!=WLD_WID )
  460.      { puts("Wrong world size");  fclose(fp);  return FALSE; }
  461.  
  462.    if( (*world=malloc((*w_rows)*(*w_cols))) == NULL )
  463.      { fclose(fp);  return FALSE; }
  464.  
  465.    fread( *world, *w_rows, *w_cols, fp );
  466.  
  467.      /* finally, the pallette */
  468.    fread( pal, 3, 256, fp );
  469.  
  470.    fclose(fp);  return TRUE;
  471.   }
  472.  
  473.                  /*-------------------------------*/
  474.  
  475. void put_tile_row( unsigned pg_off, int row, char *tiles )
  476.   {
  477.    int c, wld_x, wld_y, tilenum;
  478.    unsigned start_off;
  479.  
  480.    if( (wld_y = world_y + row) >= WLD_HGT )  wld_y -= WLD_HGT;
  481.    wld_x = world_x;
  482.  
  483.    /* alias offset so multipication done just once */
  484.    start_off = pg_off + ( (unsigned)PG_WID << 4 ) * row;
  485.  
  486.    for( c=0; c<22; c++ )
  487.       {
  488.        tilenum = world[wld_y][wld_x];
  489.        ltile_to_vram( tiles, tilenum, start_off, c<<4, 0 );
  490.  
  491.        if( ++wld_x == WLD_WID )  wld_x = 0;
  492.       }
  493.   }
  494.                  /*-------------------------------*/
  495.  
  496. void put_tile_col( unsigned pg_off, int col, char *tiles )
  497.   {
  498.    int r, wld_x, wld_y, tilenum;
  499.  
  500.    if( (wld_x = world_x + col) >= WLD_WID )  wld_x -= WLD_WID;
  501.    wld_y = world_y;
  502.  
  503.    for( r=0; r<15; r++ )
  504.       {
  505.        tilenum = world[wld_y][wld_x];
  506.        ltile_to_vram( tiles, tilenum, pg_off, col<<4, r<<4 );
  507.  
  508.        if( ++wld_y == WLD_HGT )  wld_y = 0;
  509.       }
  510.   }
  511.                  /*-------------------------------*/
  512.  
  513.